<?php
/**
 * XGPHP 轻量级PHP框架
 * @link http://xgphp.xg3.cn
 * @version 2.0.0
 * @license http://www.apache.org/licenses/LICENSE-2.0
 * @author 讯高科技 <xungaokeji@qq.com>
*/
namespace xg;
use \helper\Arr;
use \helper\Str;
use \helper\Checker;

class Request {
	protected $server;
	
	protected $params;
	protected $queryParams;
	protected $postParams;
	protected $fileMap;
	
	protected $session;
	protected $cookie;
	protected $files;
	
	protected $headers;
	protected $isSsl;
	protected $ip;
	protected $host;
	protected $domain;
	protected $referrer;
	protected $agent;
	protected $method;
	protected $uri;
	protected $isAjax=false;
	protected $baseUrl;
	protected $fullUrl;
	protected $isPost=false;
	protected $addr;

	public function __construct() {		
		$this->params = &$_REQUEST;
		$this->queryParams = &$_GET;
		$this->postParams = &$_POST;
		
		$this->session = &$_SESSION;
		$this->cookie = &$_COOKIE;
		$this->files = &$_FILES;
		$this->server = &$_SERVER;
		
		$this->params = $this->safeInput($this->params);
		$this->queryParams = $this->safeInput($this->queryParams);
		$this->postParams = $this->safeInput($this->postParams);
		$this->files = $this->safeInput($this->files);
		$this->server = $this->safeInput($this->server);
		
		// AJAX访问
		$this->isAjax=false;
		if($this->input('_ajax')){
			$this->isAjax=true;
		}elseif(strtolower($this->server['HTTP_X_REQUESTED_WITH'])=='xmlhttprequest'){
			$this->isAjax=true;
		}
		
		// HTTPS访问
		$this->isSsl=false;
		if($this->server['HTTPS']=='1' or strtolower($this->server['HTTPS'])=='on'){
			$this->isSsl=true;
		}elseif($this->server['SERVER_PORT']=='443'){
			$this->isSsl=true;
		}
		
		// 客户端IP地址
		$this->ip=$this->server['REMOTE_ADDR'];
		// 服务器IP地址
		$this->addr=$this->server['SERVER_ADDR'];
		// 访问主机名
		$this->host=$this->server['HTTP_HOST'];
		// 访问域名
		if(Checker::isDomain($this->host)){
			$this->domain=$this->host;
		}
		
		$this->referrer = $this->server['HTTP_REFERER'];
		$this->agent = $this->server['HTTP_USER_AGENT'];
		$this->method = $this->server['REQUEST_METHOD']?$this->server['REQUEST_METHOD']:'GET';
		$this->uri = $this->server['REQUEST_URI'];
		$this->baseUrl = current(explode('?',$this->server['REQUEST_URI']));
		$this->fullUrl = ($this->isSsl?'https://':'http://').$this->host.$this->uri;
		$this->isPost = ($this->method=='POST');
		
		$this->headers = $this->parseHeaders();
	}
	protected function safeInput($data){
		if(is_array($data)){
			foreach($data as $key=>$val){
				unset($data[$key]);
				$key=$this->safeInput($key);
				$val=$this->safeInput($val);
				$data[$key]=$val;
			}
		}elseif(is_string($data)){
			$data=htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
		}
		return $data;
	}
	// 获取上传的文件
	public function file($name=null){
		if(is_null($this->fileMap)){
			$this->fileMap=[];
			foreach($this->files as $key=>$file){
				if(is_array($file['name'])){
					$items=[];
					$keys=array_keys($file);
					$count=count($file['name']);
					for ($i=0;$i<$count;$i++){
						$item=[];
						foreach ($keys as $k) {
							$item[$k]=$file[$k][$i];
						}
						$items[]=$item;
					}
					$this->fileMap[$key]=$item;
				}else{
					$this->fileMap[$key]=$file;
				}
			}
		}
		if($name){
			return Arr::get($this->fileMap,$name);
		}
		return $this->fileMap;
	}
	// 请求服务器变量
	public function server($name=null) {
		if($name){
			return $this->server[Str::snakeUpper($name)];
		}
		return $this->server;
	}
	// 请求参数
	public function input(string $name,$default='',$filter=null){
		if (strpos($name,'.')) {
			list($method,$name)=explode('.',$name,2);
		} else {
			$method='request';
		}
		if (substr($name,-2)=='/i') {
			$filter='intval';
			$name=substr($name,0,-2);
		}
		if (substr($name,-2)=='/f') {
			$filter='float';
			$name=substr($name,0,-2);
		}
		switch(strtolower($method)) {
			case 'get':
				$input=$this->queryParams;
				break;
			case 'post':
				$input=$this->postParams;
				break;
			case 'put':
				parse_str(file_get_contents('php://input'),$input);
				break;
			case 'param':
				switch($this->server['REQUEST_METHOD']){
					case 'POST':
						$input=$this->postParams;
						break;
					case 'PUT':
						parse_str(file_get_contents('php://input'),$input);
						break;
					default:
						$input=$this->queryParams;
				}
				break;
			case 'request':
			case 'params':
				$input=$this->params;
				break;
			case 'session':
				$input=$this->session;
				break;
			case 'cookie':
				$input=$this->cookie;
				break;
			case 'server':
				$input=$this->server;
				break;
			case 'globals':
				$input=$GLOBALS;
				break;
			default:
				return null;
		}
		if (!$name) {
			$result=$input;
			$filters=isset($filter)?$filter:'trim,strip_tags';
			if($filter instanceof \Closure){
				if(is_array($result)){
					$result=Arr::extend(true,$filter,$result);
				}else{
					$result=$filter($result);
				}
			}elseif($filters){
				if(is_string($filters)){
					$filters=explode(',',$filters);
				}
				foreach($filters as $filter){
					$result=Arr::extend(true,$filter,$result);
				}
			}
		} elseif(isset($input[$name])) {
			$result=$input[$name];
			$filters=isset($filter)?$filter:'trim,strip_tags';
			if($filter instanceof \Closure){
				if(is_array($result)){
					$result=Arr::extend(true,$filter,$result);
				}else{
					$result=$filter($result);
				}
			}elseif($filters){
				if(is_string($filters)){
					$filters=explode(',',$filters);
				}elseif(is_int($filters)){
					$filters=array(
						$filters
					);
				}
				foreach($filters as $filter){
					if(function_exists($filter)){
						$result=is_array($result)?Arr::extend(true,$filter,$result):$filter($result);
					} else {
						$result=filter_var($result,is_int($filter)?$filter:filter_id($filter));
						if(false===$result){
							$result=$default;
						}
					}
				}
			}
		} else {
			$result=$default;
		}
		return $result;
	}

	public function __call($name, $arguments) {
		if(property_exists($this,$name)){
			return $this->$name;
		}
	}

	protected function parseHeaders(){
		$headers = [];
		foreach ($this->server as $key => $value) {
			if (strpos($key, 'HTTP_') === 0) {
				$headerName = str_replace('HTTP_', '', $key);
				$headerName = str_replace('_', '-', strtolower($headerName));
				$headers[$headerName] = $value;
			} elseif ($key === 'CONTENT_TYPE') {
				$headers['content-type'] = $value;
			} elseif ($key === 'CONTENT_LENGTH') {
				$headers['content-length'] = $value;
			}
		}
		return $headers;
	}
}